#include "atndclient.h"
#include <QtCore/QProcess>
#include <QtCore/QDateTime>
#include <QtCore/QUrl>

#include <PluginCbInterface.h>
#include <LogMacros.h>

#include <meventfeed.h>
#include <MGConfItem>

class AtndClient::Private : public QObject
{
    Q_OBJECT
public:
    Private(AtndClient *parent);

    void start();
    void abort();
    Buteo::SyncResults syncResults;

private slots:
    void finished(int exitCode, QProcess::ExitStatus exitStatus);
    void updateSettings();

private:
    void syncSuccess();
    void syncFailed();
    void updateResults(const Buteo::SyncResults &aResults);

private:
    AtndClient *q;
    QProcess *atnd;
    MGConfItem settings;
};

AtndClient::Private::Private(AtndClient *parent)
    : QObject(parent)
    , q(parent)
    , atnd(0)
    , settings("/apps/ControlPanel/ATND/EnableFeed")
{
    connect(&settings, SIGNAL(valueChanged()), this, SLOT(updateSettings()));
    if (settings.value().isNull()) {
        settings.set(true);
    }
}

void AtndClient::Private::updateSettings()
{
    if (settings.value().toBool()) {
        start();
    }
}

void AtndClient::Private::start()
{
    if (!settings.value().toBool()) return;
    if (atnd) return;
    atnd = new QProcess(this);
    connect(atnd, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus)));
    atnd->start("/opt/qatnd/bin/qatnd", QStringList() << "background");
}

void AtndClient::Private::abort()
{
    if (!atnd) return;
    atnd = new QProcess(this);
    atnd->terminate();
}

void AtndClient::Private::finished(int exitCode, QProcess::ExitStatus exitStatus)
{
    switch (exitStatus) {
    case QProcess::NormalExit:
        if (exitCode == 0) {
            syncSuccess();
        } else {
            syncFailed();
        }
        break;
    case QProcess::CrashExit:
        syncFailed();
        break;
    }
    atnd->deleteLater();
    atnd = 0;
}

void AtndClient::Private::syncSuccess()
{
    FUNCTION_CALL_TRACE;
    updateResults(Buteo::SyncResults(QDateTime::currentDateTime(), Buteo::SyncResults::SYNC_RESULT_SUCCESS, Buteo::SyncResults::NO_ERROR));
    //Notify Sync FW of result - Now sync fw will call uninit and then will unload plugin
    emit q->success(q->getProfileName(), "Success!!");
}

void AtndClient::Private::syncFailed()
{
    FUNCTION_CALL_TRACE;
    //Notify Sync FW of result - Now sync fw will call uninit and then will unload plugin
    updateResults(Buteo::SyncResults(QDateTime::currentDateTime(),
                                     Buteo::SyncResults::SYNC_RESULT_FAILED, Buteo::SyncResults::ABORTED));
    emit q->error(q->getProfileName(), "Error!!", Buteo::SyncResults::SYNC_RESULT_FAILED);
}

void AtndClient::Private::updateResults(const Buteo::SyncResults &aResults)
{
    FUNCTION_CALL_TRACE;
    syncResults = aResults;
    syncResults.setScheduled(true);
}


extern "C" AtndClient* createPlugin(const QString& aPluginName, const Buteo::SyncProfile& aProfile, Buteo::PluginCbInterface *aCbInterface)
{
    return new AtndClient(aPluginName, aProfile, aCbInterface);
}

extern "C" void destroyPlugin(AtndClient*aClient)
{
    delete aClient;
}

AtndClient::AtndClient(const QString& aPluginName, const Buteo::SyncProfile& aProfile, Buteo::PluginCbInterface *aCbInterface)
    : ClientPlugin(aPluginName, aProfile, aCbInterface)
{
    FUNCTION_CALL_TRACE;
}

AtndClient::~AtndClient()
{
    FUNCTION_CALL_TRACE;
}

bool AtndClient::init()
{
    FUNCTION_CALL_TRACE;
    d = new Private(this);
    return true;
}

bool AtndClient::uninit()
{
    FUNCTION_CALL_TRACE;
    delete d;
    return true;
}

bool AtndClient::startSync()
{
    FUNCTION_CALL_TRACE;

    d->start();

    return true;
}

void AtndClient::abortSync(Sync::SyncStatus aStatus)
{
    FUNCTION_CALL_TRACE;
    Q_UNUSED(aStatus);
    d->abort();
}

bool AtndClient::cleanUp()
{
    FUNCTION_CALL_TRACE;
    return true;
}

Buteo::SyncResults AtndClient::getSyncResults() const
{
    FUNCTION_CALL_TRACE;
    return d->syncResults;
}

void AtndClient::connectivityStateChanged(Sync::ConnectivityType aType,
                                             bool aState)
{
    FUNCTION_CALL_TRACE;
    // This function notifies of the plugin of any connectivity related state changes
    LOG_DEBUG("Received connectivity change event:" << aType << " changed to " << aState);
    if ((aType == Sync::CONNECTIVITY_INTERNET) && (aState == false)) {
        // Network disconnect!!
    }
}

#include "atndclient.moc"
